/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package cn.ekuma.epos.qkorder.ordermanager;

import cn.ekuma.epos.bean.util.erp.OrderHelper;
import cn.ekuma.epos.datalogic.I_DataLogicSystem;
import cn.ekuma.epos.qkorder.event.OrderChangedEvent;
import cn.ekuma.epos.qkorder.event.OrderChangedListener;
import com.openbravo.data.basic.BasicException;

import com.openbravo.pos.base.AppLocal;
import com.openbravo.pos.util.RoundUtils;
import com.openbravo.bean.erp.Order;
import com.openbravo.bean.erp.OrderLine;
import com.openbravo.bean.erp.OrderState;
import com.openbravo.bean.PaymentInfo;
import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.swing.table.AbstractTableModel;
import org.ofsm.IStateChangeListener;
import org.ofsm.IStateTransition;
import org.ofsm.impl.FileFiniteStateMachine;

/**
 *说明，单据的页编号可以是不连续的如(0,1,2,5,6,8,100),以便进行手动设置,但其大小应为有序.从小到大.由selectedPageIndex变量来控制上下页移动
 * 
 */
public class OrderManager extends AbstractTableModel{
   private Map<Integer,OrderPageEntry> pages;
   private Order currentOrder;
   private OrderPageEntry currentPage;
   public static int DEFAULT_SELECT_PAGE_INDEX=0;
   private boolean isEditAble;
   I_DataLogicSystem dlSystem;
   private static String[] columnName=new String[]{
                  AppLocal.getIntString("label.ordermanager.pageindex"),
                  AppLocal.getIntString("label.units"),
                  AppLocal.getIntString("label.taxcash"),
                  AppLocal.getIntString("label.totalcash")};
   FileFiniteStateMachine stateMachine;
   
    public OrderManager(I_DataLogicSystem dlSystem) {
        this.dlSystem=dlSystem;
        stateMachine=new FileFiniteStateMachine();
        addStateChangeListener( new IStateChangeListener(){
            public boolean onStateChanging(IStateTransition transition) {
                return true;
            }

            public void onStateChanged(IStateTransition transition, String memo) {
                fireOrderChanged();
            }
        });
        stateMachine.setCurrentState(AppLocal.getIntString(OrderState.ORDERSTATE_End));
        pages=new TreeMap<Integer,OrderPageEntry>();
        isEditAble=false;
        currentPage=new OrderPageEntry(DEFAULT_SELECT_PAGE_INDEX);
        pages.put(DEFAULT_SELECT_PAGE_INDEX, currentPage);
    }

   public void setOrder(Order order,boolean isEditAble) throws BasicException{
       currentOrder=order;
       this.isEditAble=isEditAble;
       pages.clear();
       currentPage=new OrderPageEntry(DEFAULT_SELECT_PAGE_INDEX);
       pages.put(DEFAULT_SELECT_PAGE_INDEX, currentPage);  
       buildPageEntry();
       initStateMachine();
       fireTableDataChanged();
       fireOrderChanged();
   }

    private void initStateMachine() throws BasicException{
        String stateMachineName = currentOrder.getDefineType().getStateMachine();
        String currentState = currentOrder.getCurrentState();
        if (stateMachineName == null || stateMachineName.isEmpty()) {
        } else {
            byte[] bf = dlSystem.getResourceAsBinary(stateMachineName);
            if (bf != null) {
                ByteArrayInputStream btStream = new ByteArrayInputStream(bf);
                try {
                    stateMachine.init(btStream);
                    stateMachine.setCurrentState(currentState);
                } catch (Exception ex) {
                   throw new BasicException(ex);
                }
            }
        }
    }

   public void addStateChangeListener(IStateChangeListener l){
       stateMachine.addStateChangeListener(l);
   }

   public void removeStateChangeListener(IStateChangeListener l){
        stateMachine.delStateChangeListener(l);
   }

    public boolean isEditAble() {
        return isEditAble;
    }

    public void setEditAble(boolean isEditAble) {
        this.isEditAble = isEditAble;
    }

   //页操作
   public void pageUp(){
       Iterator<OrderPageEntry> list=pages.values().iterator();
       OrderPageEntry before=list.next();
       OrderPageEntry temp;
       while(list.hasNext()){
           temp=list.next();
           if(this.currentPage.equals(temp)){
               currentPage=before;
               firePageChanged();
               break;
           }
           before=temp;
       }
   }

   public void pageDown(){
       Iterator<OrderPageEntry> list=pages.values().iterator();
       OrderPageEntry temp;
       while(list.hasNext()){
           temp=list.next();
           if(currentPage.equals(temp)&&list.hasNext()){
               currentPage=list.next();
               firePageChanged();
               break;
           }
       }
   }

   public void selectPage(int select){
        OrderPageEntry selectedPage=pages.get(select);
        if(selectedPage==null){
           if(!isEditAble())
               return;
           currentPage=new OrderPageEntry(select);
           pages.put(currentPage.getPageIndex(), currentPage);
           firePageChanged();
           fireTableDataChanged();
         }else{
            currentPage=selectedPage;
            firePageChanged();
         }
   }

   public void pageFirst(){
       Iterator<OrderPageEntry> list=pages.values().iterator();
       OrderPageEntry first=list.next();
       if(!currentPage.equals(first)){
            currentPage=first;
            firePageChanged();
       }
   }
   
   public void pageEnd(){
       Iterator<OrderPageEntry> list=pages.values().iterator();
       OrderPageEntry end = list.next();
       while(list.hasNext()){
           end=list.next();
       }
       if(!this.currentPage.equals(end)){
            currentPage=end;
            firePageChanged();
       }
   }

   public int getPageCount(){
      return pages.size();
   }

   public OrderPageEntry getCurrentPage(){
       return currentPage;
   }

   //当前页包装类
   public void setOrderLine(List<OrderLine> lines){
	   currentPage.setOrderLines(lines);
   }
   
   public OrderLine getLine(int index) {
        return currentPage.getLine(index);
    }

   public Iterable<OrderLine> getLines() {
        return this.currentPage.getLines();
    }

    public void addLine(OrderLine oLine) {
        currentPage.addLine(oLine);
    }

    public void insertLine(int index, OrderLine oLine) {
        currentPage.insertLine(index, oLine);
    }

    public void setLine(int index, OrderLine oLine) {
       currentPage.setLine(index, oLine);
    }

    public void removeLine(int index) {
       currentPage.removeLine(index);
    }

    public int getLinesCount() {
        return currentPage.getLinesCount();
    }

    public String printSubTotal() {
        return currentPage.printSubTotal();
    }

    public String printTax() {
        return currentPage.printTax();
    }

    public String printTotal() {
        return currentPage.printTotal();
    }
    
    public String printDefSubTotal() {
        return currentPage.printDefaultSubTotal();
    }

    public String printDefTax() {
        return currentPage.printDefaultTax();
    }

    public String printDefTotal() {
        return currentPage.printDefaultTotal();
    }
    
    public String printArticlesCount(){
        return currentPage.printArticlesCount();
    }
    

    ////////////////////整单相关类
    public String printDate() {
        return OrderHelper.printDate(currentOrder);
    }

    public String printUser() {
       return OrderHelper.printUser(currentOrder);
    }

    public String printCustomer() {
        return OrderHelper.printCustomer(currentOrder);
    }

    public String printPriceRate(){
        return OrderHelper.printPriceRate(currentOrder);
    }

   public OrderPageEntry getPage(int index){
       return new ArrayList<OrderPageEntry>(pages.values()).get(index);
   }

   public int getOrderLinesCount(){
       int lineCount=0;
       Iterator<OrderPageEntry> list=pages.values().iterator();
       while(list.hasNext()){
           lineCount+=list.next().getLinesCount();
       }
       return lineCount;
   }

    /**
     * 事件相关
     * @param l
     */

   public void addPageChangeListener(PageChangeListener l){
       listenerList.add(PageChangeListener.class, l);
   }

   public void removePageChangeListener(PageChangeListener l){
       listenerList.remove(PageChangeListener.class, l);
   }

   public PageChangeListener[] getPageChangeListeners() {
        return (PageChangeListener[])listenerList.getListeners(
                PageChangeListener.class);
    }

    public void firePageChanged() {
        firePageChanged(new PageChangeEvent(this,currentPage.getPageIndex()));
    }


    public void firePageChanged(PageChangeEvent e) {
	// Guaranteed to return a non-null array
	Object[] listeners = listenerList.getListenerList();
	// Process the listeners last to first, notifying
	// those that are interested in this event
	for (int i = listeners.length-2; i>=0; i-=2) {
	    if (listeners[i]==PageChangeListener.class) {
		((PageChangeListener)listeners[i+1]).pageChanged(e);
	    }
	}
    }

    public void addOrderChangedListener(OrderChangedListener l){
        listenerList.add(OrderChangedListener.class, l);
    }

    public void removeOrderChangeListener(OrderChangedListener l){
       listenerList.remove(OrderChangedListener.class, l);
   }

    public OrderChangedListener[] getOrderChangedListeners() {
        return (OrderChangedListener[])listenerList.getListeners(OrderChangedListener.class);
    }

     public void fireOrderChanged() {
        fireOrderChanged(new OrderChangedEvent(currentOrder,isEditAble));
    }

    public void fireOrderChanged(OrderChangedEvent e) {
	// Guaranteed to return a non-null array
	Object[] listeners = listenerList.getListenerList();
	// Process the listeners last to first, notifying
	// those that are interested in this event
	for (int i = listeners.length-2; i>=0; i-=2) {
	    if (listeners[i]==OrderChangedListener.class) {
		((OrderChangedListener)listeners[i+1]).orderChanged(e);
	    }
	}
    }


    private void buildPageEntry() {
       List<OrderLine> lines=currentOrder.getLines();
       if(lines!=null){
           OrderLine line;
           int linePageIndex;
           for(int i=0;i<lines.size();i++){
              line=lines.get(i);
              linePageIndex=line.getPageIndex();
              currentPage=pages.get(linePageIndex);
              if(currentPage==null){
                  currentPage=new OrderPageEntry(linePageIndex);
                  pages.put(currentPage.getPageIndex(), currentPage);
              }
              currentPage.addLine(line);
           }
       }
    }


    public List<OrderLine> buildOrderLines(){
       List<OrderLine> orderLines=new ArrayList();
       Iterator<OrderPageEntry> list=pages.values().iterator();
       while(list.hasNext()){
           orderLines.addAll(list.next().getLines());
       }
       return orderLines;
    }

    public Order getOrder(){
        return currentOrder;
    }
    
    

    /******************************
     * tableModel
     * 
     */
    @Override
    public int getRowCount() {
       return this.getPageCount();
    }

    @Override
    public int getColumnCount() {
        return columnName.length;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        OrderPageEntry selectpage=getPage(rowIndex);
        switch(columnIndex){
            case 0:
                return selectpage.getPageIndex();
            case 1:
                return selectpage.printArticlesCount();
            case 2:
                return selectpage.printTax();
            case 3:
                return selectpage.printTotal();
        }
        return null;
    }

    @Override
    public String getColumnName(int column) {
        return columnName[column];
    }

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    public double getOrderPriceTotal() {
       double priceTotal=0.0;
       Iterator<OrderPageEntry> list=pages.values().iterator();
       while(list.hasNext()){
           OrderPageEntry page=list.next();
           priceTotal=RoundUtils.add(priceTotal,page.getTotal());
       }
       return priceTotal;
    }

    public Collection<OrderPageEntry> getPages(){
        return pages.values();
    }

    public void addLines(List<OrderLine> lines) {
       Iterator<OrderPageEntry> list=pages.values().iterator();
       OrderPageEntry end = list.next();
       while(list.hasNext()){
           end=list.next();
       }
       int basePageNum=end.getPageIndex();
       if(end.getLinesCount()!=0)
           basePageNum++;
        for(OrderLine line:lines){
              end=pages.get(basePageNum+line.getPageIndex());
              if(end==null){
                   end=new OrderPageEntry(basePageNum+line.getPageIndex());
                   pages.put(end.getPageIndex(), end);
              }
              end.addLine(line);
        }
        firePageChanged();
        fireTableDataChanged();
    }

   public OrderLine getOrderLineByProductId(String productID, String attributesetid) {
       for(OrderLine line:buildOrderLines()){
             String curAttId=line.getProductAttSetInstId();
             if(productID.equalsIgnoreCase(line.getProductID()))
                 if(curAttId==null&&attributesetid==null||curAttId!=null&&curAttId.equals(attributesetid))
                     return line;
         }
         return null;
    }

    public int getOrderLineIndexInCurrentPage(OrderLine inOrderLine) {
       List lines=currentPage.getLines();
        for(int i=0;i<lines.size();i++){
            if(lines.get(i).equals(inOrderLine)){
                return i;
            }
        }
        return -1;
    }

    public FileFiniteStateMachine getStateMachine() {
        return stateMachine;
    }

    public void setPayments(List<PaymentInfo> selectedPayments) {
        currentOrder.setPayments(selectedPayments);
        currentOrder.setDebt(0.0);
        for(PaymentInfo p:selectedPayments){
    		if("debt".equals(p.getName())){
    			currentOrder.setDebt(p.getTotal());
    			break;
    		}
    	}
        this.fireOrderChanged();
    }
    
}
